package org.csu.laboratoryequipment.model;

import org.apache.commons.lang3.StringUtils;
import org.csu.laboratoryequipment.entity.CompKeyWord;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class CompKeyAlgorithm {
    public static int compNum = 10; //竞争关键词个数
    public static int midNum = 10; //中介关键词数量
    public static int compCandidateNum = 20; //候选竞争关键词的数量
    public List<CompKeyWord> comKeyAlgorithm(String seedKey) throws IOException {
        //建立以该种子关键字命名保存中介关键字的文件夹
        File folder = new File(FilePath.MIDKEY_FILE_PRIFIX + "/" + seedKey);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        /**
         * 1、从实验一中结果包含种子关键字的搜索记录中查找中介关键字
         */
        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(FilePath.SEED_SEARCH_FILE_PRIFIX + "/" + seedKey + ".txt"), StandardCharsets.UTF_8);
        BufferedReader br = new BufferedReader(inputStreamReader);
        //记录包含种子关键字的文件中各短语出现的个数，作为中介关键词的候选项
        Map<String, Integer> middleMap = new HashMap<>();
        String line = null;
        while (true) {
            line = br.readLine();
            if (line == null) {
                break;
            } else {
                List<String> arrlist = Arrays.asList(line.split("\\s+"));
                List<String> list = new ArrayList(arrlist);
                //过滤种子关键字，不区分大小写
                list.removeIf(a -> StringUtils.containsIgnoreCase(a, seedKey));
                //过滤一个字的关键词
                list.removeIf(a -> a.length() < 2);
                //剩下的作为中介词备选
                for (String string : list) {
                    //保存时全部用小写保存
                    string = string.toLowerCase();
                    if (middleMap.containsKey(string)) {
                        int n = middleMap.get(string);
                        middleMap.put(string, n + 1);

                    } else {
                        middleMap.put(string, 1);
                    }
                }
            }
        }
        //重写比较规则对包含中介关键词及其次数的哈希表进行降序排列
        Comparator<Map.Entry<String, Integer>> valueComparator = (o1, o2) -> o2.getValue() - o1.getValue();
        //将Map键值对转换成新的List集合
        List<Map.Entry<String, Integer>> list = new ArrayList<>(middleMap.entrySet());
        //对备选中介关键词进行排序
        Collections.sort(list, valueComparator);
        List<String> midKeys = new ArrayList<>();
        //根据频率和约定的中介关键词数量选择中介关键词
        for (int i = 0; i < midNum; i++) {
            Map.Entry<String, Integer> entry = list.get(i);
            midKeys.add(entry.getKey());
        }
        System.out.println(midKeys);
        /**
         * 2、获取包含中介关键字和种子关键字的联合搜索量
         */
        //从包含种子关键字的文件中查找
        InputStreamReader inputStreamReader1 = new InputStreamReader(new FileInputStream(FilePath.SEED_SEARCH_FILE_PRIFIX + "/" + seedKey + ".txt"), StandardCharsets.UTF_8);
        br = new BufferedReader(inputStreamReader1);
        OutputStreamWriter outputStreamWriter3 = new OutputStreamWriter(new FileOutputStream(FilePath.MIDKEY_FILE_PRIFIX + "/" + seedKey + "/" + "中介关键字搜索.txt"), StandardCharsets.UTF_8);
        BufferedWriter bw3 = new BufferedWriter(outputStreamWriter3);

        int s_size = 0;  //定义{s}
        int sa_size[] = new int[midNum];  //定义{sa}
        double weight_a[] = new double[midNum];

        while (true) {
            line = br.readLine();
            if (line == null) {
                break;
            } else {
                s_size++;
                for (int i = 0; i < midNum; i++) {
                    if (line.contains(midKeys.get(i))) {
                        sa_size[i]++;
                    }
                }
            }
        }
        System.out.println(s_size);

        /**
         * 3、计算权重
         */
        for (int i = 0; i < midNum; i++) {
            weight_a[i] = 1.0* sa_size[i] / s_size;
            System.out.println(weight_a[i]);
        }

        /**
         * 4、确定竞争性关键字候集合
         */
        //读取分词结果 中包含中介关键词而不含种子关键词的记录
        InputStreamReader inputStreamReader2 = new InputStreamReader(new FileInputStream(FilePath.JIEBA_DIVIDE_WORD_FILE_NAME), StandardCharsets.UTF_8);
        br = new BufferedReader(inputStreamReader2);
        File file = new File(FilePath.MIDKEY_FILE_PRIFIX+ "/" + seedKey+"分词包含所有中介搜索.txt");
        file.getParentFile().mkdirs();

        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
        BufferedWriter bw = new BufferedWriter(outputStreamWriter);
        line = null;

        while ((line = br.readLine())!=null){
            if (line == null) {
                break;
            }
            if(line.contains(seedKey)) {
                continue;
            }
            for (int i = 0; i < midNum; i++) {
                if (line.contains(midKeys.get(i))) {
                    bw.append(line);
                    bw.newLine();
                    bw.flush();
                    break;
                }
            }
        }
        //分词结果中包含中介关键词的记录进行词语计数，保留最多的20个作为候选竞争关键字
        InputStreamReader inputStreamReader3 = new InputStreamReader(new FileInputStream(FilePath.MIDKEY_FILE_PRIFIX+ "/" + seedKey+"分词包含所有中介搜索.txt"), StandardCharsets.UTF_8);
        br = new BufferedReader(inputStreamReader3);
        Map<String, Integer> condidateMap = new HashMap<>();
        while (true) {
            line = br.readLine();
            if (line == null) {
                break;
            } else {
                List<String> arrlist = Arrays.asList(line.split("\\s+"));
                List<String> list1 = new ArrayList(arrlist);
                //过滤 中介关键词 由于不能是中介关键字
                for (int i=0;i<midNum;i++) {
                    int finalI = i;
                    list1.removeIf(a -> StringUtils.containsIgnoreCase(a, midKeys.get(finalI)));
                }
                //过滤一个字的关键词
                list1.removeIf(a -> a.length() < 2);
                //剩下的作为备选竞争关键词
                for (String string : list1) {
                    //保存时全部用小写保存
                    string = string.toLowerCase();
                    if (condidateMap.containsKey(string)) {
                        int n = condidateMap.get(string);
                        condidateMap.put(string, n + 1);
                    } else {
                        condidateMap.put(string, 1);
                    }
                }
            }
        }
        //重写比较规则对包含中介关键词及其次数的哈希表进行降序排列
        Comparator<Map.Entry<String, Integer>> valueComparator1 = (o1, o2) -> o2.getValue() - o1.getValue();
        //将Map键值对转换成新的List集合
        List<Map.Entry<String, Integer>> list1 = new ArrayList<>(condidateMap.entrySet());
        //对备选中介关键词进行排序
        Collections.sort(list1, valueComparator1);
        List<String> condidateKeys = new ArrayList<>();
        //根据频率和约定的中介关键词数量选择中介关键词
        for (int i = 0; i < compCandidateNum; i++) {
            Map.Entry<String, Integer> entry = list1.get(i);
            condidateKeys.add(entry.getKey());
        }
        System.out.println(condidateKeys);

        /**
         * 5、计算竞争性关键字的竞争度，利用ka/a-sa
         */
        int[]a =new int[midNum];
        int[][]ka = new int[midNum][compCandidateNum];
        double[][] comp_k = new double[midNum][compCandidateNum];//每个竞争词在不同中介词下和关键词s的竞争度
        br = new BufferedReader(new InputStreamReader(new FileInputStream(FilePath.JIEBA_DIVIDE_WORD_FILE_NAME), StandardCharsets.UTF_8));//分词包含所有中介搜索
        while (true) {
            line = br.readLine();
            if (line == null) {
                break;
            }
            for (int i = 0; i < midNum; i++) {
                if (line.contains(midKeys.get(i))) {
                    a[i]=a[i]+1;
                    for (int j = 0; j < compCandidateNum; j++) {
                        if (line.contains(condidateKeys.get(j))) {
                            ka[i][j]++;
                        }
                    }
                }
            }
        }

        for (int i=0;i<midNum;i++)
        {
            for (int j=0;j<compCandidateNum;j++)
            {

                comp_k[i][j] = (1.0 * ka[i][j])/(a[i]-sa_size[i]);
            }
        }
        /**
         * 6、计算竞争性关键字的竞争度求和
         */
        File file1 = new File(FilePath.MIDKEY_FILE_PRIFIX+ "/" + seedKey+"候选关键字最终结果.txt");
        file.getParentFile().mkdirs();
        OutputStreamWriter outputStreamWriter2 = new OutputStreamWriter(new FileOutputStream(file1), StandardCharsets.UTF_8);
        BufferedWriter bw2 = new BufferedWriter(outputStreamWriter2);
        Map<String, Double> map1 = new HashMap<>();
        for (int i=0;i<compCandidateNum;i++)
        {
            double sum=0;
            for (int j=0;j<midKeys.size();j++)
            {
                sum += weight_a[j]*comp_k[j][i];
            }
            map1.put(condidateKeys.get(i),sum);
        }
        //重写比较规则对包含竞争关键词及其次数的哈希表进行降序排列
        Comparator<Map.Entry<String, Double>> valueComparator3 = (o1, o2) -> Double.compare(o2.getValue(), o1.getValue());
        //将Map键值对转换成新的List集合
        List<Map.Entry<String, Double>> list3 = new ArrayList<>(map1.entrySet());
        Collections.sort(list3, valueComparator3);

        List<CompKeyWord> result = new ArrayList<>();


        for (int i = 0; i < compNum; i++) {
            Map.Entry<String, Double> entry = list3.get(i);
            bw2.append(entry.getKey()+" 的竞争度是:"+entry.getValue());
            bw2.newLine();
            bw2.flush();
            System.out.println(entry.getKey()+" 的竞争度是:"+entry.getValue());
            CompKeyWord temp = new CompKeyWord();
            temp.setCom_num(entry.getValue());
            temp.setCom_word(entry.getKey());
            result.add(temp);
        }
        return result;
    }
}